package com.iuie.ns.frame.web.dataset.context;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.iuie.ns.frame.web.dataset.annotation.DataField;
import com.iuie.ns.frame.web.dataset.annotation.DataFieldAttribute;
import com.iuie.ns.frame.web.dataset.annotation.ExtraDataField;
import com.iuie.ns.frame.web.dataset.description.DataFieldDescription;
import com.iuie.ns.frame.web.dataset.vo.ColsVO;

class DataFieldAnnotationHandler {
	private static Logger logger = LoggerFactory.getLogger(DataFieldAnnotationHandler.class);
	
	Map<Class<?>, String> DATA_TYPE_MAPPING = new HashMap<Class<?>, String>(){
		private static final long serialVersionUID = 7008625246606293651L;

		{
			put(java.lang.String.class, "string");
			put(java.lang.Integer.class, "number");
			put(java.lang.Long.class, "number");
			put(java.lang.Float.class, "number");
			put(java.lang.Double.class, "number");
			put(java.lang.Character.class, "string");
			put(java.util.Date.class, "date");
			put(java.lang.Boolean.class, "string");
			// 基本数据类型
			put(char.class, "string");
			put(double.class, "number");
			put(float.class, "number");
			put(long.class, "number");
			put(int.class, "number");
			put(short.class, "number");
			put(boolean.class, "string");
		}
	};
	
	private Field field;
	
	private Set<String> dataSetNames;
	
	private DataFieldDescription description;
	
	protected DataFieldAnnotationHandler(Field field,Set<String> dataSetNames) {
		this.field = field;
		this.dataSetNames = dataSetNames;
		this.description = new DataFieldDescription();
	}
	
	protected DataFieldDescription handle(){
		DataField dataField = field.getAnnotation(DataField.class);
		if (dataField == null) {
			return null;
		}
		String fieldName = field.getName();
		
		description.setName(fieldName);
		
		Class<?> type = field.getType();
		String dataType = processDataType(type); 
		description.setType(dataType);
		
		// 处理并得到DataField的描述信息
		// 获取并设置ColsVO中定义的属性值
		description.setIgnore(dataField.ignore());
		description.setDataCssClass(dataField.dataCssClass());
		description.setFlex(dataField.flex());
		description.setSort(dataField.sort());
		description.setText(dataField.text());
		
		if (java.util.Date.class.isAssignableFrom(field.getType())) {
			description.setDateFormat(dataField.dateFormat());
		}
		if(!dataField.type().isEmpty())
			description.setType(dataField.type());
		description.setWidth(dataField.width());

		// 获取并设置 DataFieldDescription 中定义的属性 
		description.setDataSetName("");
		description.setInvokeMethodName(dataField.invokeMethodName());
		description.setFieldOfFiledName(dataField.fieldOfFiledName());
		description.setFieldOfMethodName(dataField.fieldOfMethodName());
		
		ExtraDataField[] others = dataField.others();
		for(ExtraDataField other:others){
			DataFieldDescription o = new DataFieldDescription(description);
			if (!this.dataSetNames.contains(other.dataSetName())) {
				throw new RuntimeException("DataSet中没有定义name= " + other.dataSetName()+"的值");
			}
			o.setDataSetName(other.dataSetName());
			DataFieldAttribute[] attributes = other.attributes();
			for(DataFieldAttribute attribute:attributes){
				String name = attribute.name();
				String value = attribute.value();
				try {
					Field f = ColsVO.class.getDeclaredField(name);
					f.setAccessible(true);
					Object obj = null;
					if(f.getType()==java.lang.Boolean.class){
						obj = Boolean.valueOf(value);
					} else if (f.getType()==java.lang.Integer.class) {
						obj = Integer.valueOf(value);
					} else {
						obj = value;
					}
					f.set(o, obj);
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
					logger.error("给" + DataFieldDescription.class.getName() +"的对象设置 " + name
							+ "的属性值为：" + value+"时失败！");
				} catch (IllegalAccessException e) {
					e.printStackTrace();
					logger.error("不允许给" + DataFieldDescription.class.getName() +"的对象设置 " + name
							+ "属性");
				} catch (SecurityException e) {
					e.printStackTrace();
					logger.error(e.getMessage());
				} catch (NoSuchFieldException e) {
					e.printStackTrace();
					logger.error(e.getMessage());
				}
			}
			description.addOther(o);
		}
		return description;
	}

	/*
	 * 处理数据类型
	 */
	private String processDataType(Class<?> clazz){
		Class<?> class1 = null;
		String type = null;
		if(DATA_TYPE_MAPPING.containsKey(clazz)){
			type = DATA_TYPE_MAPPING.get(clazz);
		} else if((class1 = getClazzAssignableFroms(clazz)) != null){ // 判断clazz是否为DATA_TYPE_MAPPING中某一个的子类
			type = DATA_TYPE_MAPPING.get(class1);
		} else {
			//----------------------//
			type="object";
			//----------------------//
//			throw new UnSupportFieldTypeException("不支持类：" + clazz.getName()+" 作为属性：" + field.getName()
//					+" 的数据类型，DataField注解不能作用于" + clazz.getName() + "类型的属性上");
		}
		return type;
	}
	
	/*
	 * 判断clazz是否是 DATA_TYPE_MAPPING中定义的类对应的子类
	 * @param clazz
	 * @return
	 */
	private Class<?> getClazzAssignableFroms(Class<?> clazz){
		Iterator<Entry<Class<?>, String>> it = DATA_TYPE_MAPPING.entrySet().iterator();
		while(it.hasNext()){
			Class<?> class1 = it.next().getKey();
			if (class1.isAssignableFrom(clazz)) {
				return class1;
			}
		}
		return null;
	}
}
